package com.iwhalecloud.bss.kite.cucc.web.service.accept.handler.module;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.github.pagehelper.PageInfo;
import com.iwhalecloud.bss.kite.client.vo.scene.ModuleVO;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.ServiceOfferConsts;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteObjectUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.client.api.account.ILocalAccountService;
import com.iwhalecloud.bss.kite.cucc.client.api.reception.ICustReceptionService;
import com.iwhalecloud.bss.kite.cucc.client.dto.account.CustAccountDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.account.QryCustAccountReq;
import com.iwhalecloud.bss.kite.cucc.client.dto.cust.CuccContextCustDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.scene.CuccCustInfoDetailDTO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.AccountModuleVO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.AccountRelVO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.SceneNewOfferSeneVO;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalKeyConsts;
import com.iwhalecloud.bss.kite.cucc.common.util.DateFormatUtils;
import com.iwhalecloud.bss.kite.cucc.common.util.DateUtils;
import com.iwhalecloud.bss.kite.cucc.manager.inst.CuccKiteOfferInstAcct;
import com.iwhalecloud.bss.kite.cucc.manager.scene.service.operate.LocalOperateOfferInstAcctRelService;
import com.iwhalecloud.bss.kite.cucc.service.attr.LocalAttrHelper;
import com.iwhalecloud.bss.kite.cucc.service.batch.BatchAcceptUtil;
import com.iwhalecloud.bss.kite.cucc.service.goods.GoodsHelper;
import com.iwhalecloud.bss.kite.cucc.service.util.KiteDcPublicUtils;
import com.iwhalecloud.bss.kite.cucc.spec.impl.transfer.GoodsInfoTransfer;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferCache;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Offer;
import com.iwhalecloud.bss.kite.manager.api.IOperateSceneInstService;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.enums.RelType;
import com.iwhalecloud.bss.kite.manager.inst.KiteAttr;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteSceneInst;
import com.iwhalecloud.bss.kite.web.context.KiteWebContext;
import com.iwhalecloud.bss.kite.web.service.accept.bo.AcceptContext;
import com.iwhalecloud.bss.kite.web.service.accept.bo.SceneModule;
import com.iwhalecloud.bss.kite.web.service.accept.handler.module.AbstractModuleHandler;
import com.iwhalecloud.bss.pub.client.constanst.Symbols;
import com.ztesoft.bss.base.staticdata.ServiceOfferConst;
import com.ztesoft.bss.common.util.ContextUtil;
import com.ztesoft.bss.common.util.SpringUtil;
import com.ztesoft.bss.svcability.util.ListUtil;
import com.ztesoft.common.logger.api.ZLogger;
import com.ztesoft.common.logger.factory.ZLoggerFactory;

@Service
public class AccountRelInfoModuleHandler extends AbstractModuleHandler {

    private static final ZLogger LOGGER = ZLoggerFactory
        .getLogger(AccountRelInfoModuleHandler.class, KeyConsts.LOG_MODULE);

    @Autowired
    private IQuerySceneInstService querySceneInstService;

    @Autowired
    private LocalOperateOfferInstAcctRelService operateOfferInstAcctRelService;

    @Autowired
    IOperateSceneInstService operateSceneInstService;

    @Autowired
    private ICustReceptionService custReceptionService;

    @Autowired
    private ILocalAccountService accountService;

    @Override
    public List<AccountModuleVO> execute(AcceptContext context, SceneModule sceneModule) {

        SceneNewOfferSeneVO sceneAccountInfoVo = (SceneNewOfferSeneVO) context.getSceneVo();

        //收入归集创建,需要默认创建本客户下有Cbss账户标识的付费关系
        List<AccountRelVO> accountRelVos = (List<AccountRelVO>) querySceneInstService
            .getExtParameter(context.getSceneVo().getSceneInstId())
            .get(context.getSceneVo().getSceneInstId() + "_ACCOUNTRELVOS");
        if (KiteListUtils.isEmpty(accountRelVos) && KiteDcPublicUtils
            .isCollectionGroup(context.getSceneVo().getSceneInstId())) {
            KiteOfferInst kiteOfferInst = querySceneInstService.getMainOfferInst(context.getSceneVo().getSceneInstId());
            if (!KiteObjectUtils.isEmpty(kiteOfferInst) && KiteStringUtils
                .isNotEmpty(context.getAcceptRequest().getCustId())) {
                CuccCustInfoDetailDTO cuccCustInfoDTO = custReceptionService
                    .getCustomerInfoNew(context.getAcceptRequest().getCustId());
                dealAccount(cuccCustInfoDTO, kiteOfferInst, context.getSceneVo().getSceneInstId());
            }
        }

        String changeSceneFlag = querySceneInstService
            .getExtParameterValue(context.getSceneVo().getSceneInstId(), LocalKeyConsts.BUSI_CHANGE_SCENE);
        AccountModuleVO accountModuleVO = new AccountModuleVO();
        if (KiteStringUtils.isEqual("T", changeSceneFlag)) {
            accountModuleVO = getAccountModule(context, Boolean.TRUE);

        }
        else {
            accountModuleVO = getAccountModule(context, Boolean.FALSE);
        }

        // 融合产品变更--不允许修改付费关系
        if (!KiteObjectUtils.isEmpty(context.getAcceptRequest()) && KiteStringUtils
            .isNotEmpty(context.getAcceptRequest().getOfferId()) && GoodsHelper
            .isGift(context.getAcceptRequest().getOfferId()) && KiteStringUtils
            .isEqual(ServiceOfferConsts.SERVICE_OFFER_MODIFY, context.getAcceptRequest().getServiceOfferId())) {
            accountModuleVO.setIsEdit("F");
        }

        // 批量受理部分环节，不允许编辑
        if (BatchAcceptUtil.isBatchNode(context.getAcceptRequest().getSceneInstId())
            || BatchAcceptUtil.batchNodeResetIsEdit(context.getAcceptRequest().getSceneInstId())) {
            accountModuleVO.setIsEdit("F");
        }

        sceneAccountInfoVo.setAccount(accountModuleVO);

        return Collections.singletonList(accountModuleVO);
    }

    @Override
    public List<ModuleVO> previewSceneVo(AcceptContext context, SceneModule sceneModule) {

        SceneNewOfferSeneVO sceneNewOfferSeneVO = (SceneNewOfferSeneVO) context.getSceneVo();
        AccountModuleVO accountModuleVO = getAccountModule(context, Boolean.TRUE);
        accountModuleVO.setIsEdit(KeyConsts.IFTRUE_F);
        sceneNewOfferSeneVO.setAccount(accountModuleVO);
        return Collections.singletonList(accountModuleVO);
    }

    @SuppressWarnings("unchecked")
    private AccountModuleVO getAccountModule(AcceptContext context, Boolean isPreview) {
        String sceneInstId = context.getSceneVo().getSceneInstId();
        // 批量受理当前修改销售品实例标识，存在则说明是批量受理的单个修改场景
        String curOfferInstId = context.getAcceptRequest().getCurOfferInstId();

        List<AccountRelVO> accountRelVos = new ArrayList<>();
        KiteSceneInst sceneInst = this.querySceneInstService.getSceneInst(sceneInstId);
        String sceneOperType = sceneInst.getOperType();
        String rootInstId = sceneInst.getRootInstId();
        KiteOfferInst offerInst = querySceneInstService.getOfferInst(sceneInst.getCustId(), rootInstId);
        // 批量受理的单个修改，只处理当前修改的销售品实例
        if (KiteStringUtils.isNotEmpty(curOfferInstId)) {
            offerInst = querySceneInstService.getOfferInst(sceneInst.getCustId(), curOfferInstId);
        }
        // TODO: 批量受理的单个修改时这里要改
        KiteAttr accNumAttr = querySceneInstService.getCommonAttr(sceneInstId, "business_number");
        String accNum = accNumAttr != null ? accNumAttr.getValue() : "";
        if (isPreview || LocalKeyConsts.KITE_SCENE_INST_OPER_TYPE_1003.equals(sceneOperType)) {
            //预览会去查询list数据
            List<AccountRelVO> oldAccountRelVos = (List<AccountRelVO>) querySceneInstService
                .getExtParameter(sceneInstId).get(sceneInstId + "_ACCOUNTRELVOS");

            String cateId = Optional.ofNullable(offerInst.getAttr("cateId")).map(KiteAttr::getDefaultValue).orElse("");
            if (!GoodsInfoTransfer.isAddRoleOffer(offerInst.getSpecId(), cateId)) {
                List<CuccKiteOfferInstAcct> accountRels = KiteBeanUtils.copyPropsForList(operateOfferInstAcctRelService.listOfferInstAccts(context.getAcceptRequest().getCustId(), offerInst.getOfferInstId()), CuccKiteOfferInstAcct.class);
                accountRels.stream().forEach(acctRel -> {
                    AccountRelVO oldAccountRelVO = new AccountRelVO();
                    if (KiteListUtils.isNotEmpty(oldAccountRelVos)) {
                        oldAccountRelVO = oldAccountRelVos.get(0);
                    }
                    AccountRelVO accountRel = new AccountRelVO();
                    accountRel.setOfferInstId(acctRel.getOfferInstId());
                    accountRel.setOfferName(acctRel.getOfferName());
                    accountRel.setAcctId(acctRel.getAcctId());
                    accountRel.setAcctName(acctRel.getAcctName());
                    accountRel.setAcctItemId(acctRel.getAcctItemId());
                    accountRel.setInstId(acctRel.getInstId());
                    accountRel.setIsDefault(acctRel.getIsDefault());
                    accountRel.setPayWay(acctRel.getPayWay());
                    accountRel.setPayLimit(acctRel.getPayLimit());
                    accountRel.setAccNum(accNum);
                    accountRel.setCustName(acctRel.getCustName());
                    accountRel.setContractId(acctRel.getContractId());
                    accountRel.setCustId(acctRel.getCustId());

                    String cbssAccountCode = acctRel.getCbssAccountCode();
                    if(KiteStringUtils.isBlank(cbssAccountCode)){
                        CuccContextCustDTO cuccContextCustDTO = (CuccContextCustDTO) KiteWebContext.getContext().getCust();
                        String provinceCode = cuccContextCustDTO.getProvinceCode();
                        String eparchyCode = cuccContextCustDTO.getEparchyCode();
                        PageInfo<QryCustAccountReq> list = accountService
                            .listCustAccountInfo(acctRel.getCustId(), "", "", acctRel.getAcctId(), "", "", "", provinceCode,
                                eparchyCode,null, 1, 5);
                        List<QryCustAccountReq> infResult = list.getList();
                        if (KiteListUtils.isNotEmpty(infResult)) {
                            QryCustAccountReq req = infResult.get(0);
                            cbssAccountCode =  req.getCustAccount().getCbssAccountCode();
                        }
                    }
                    accountRel.setCbssAccountCode(cbssAccountCode);

                    if (!KiteStringUtils
                        .isEqual(context.getAcceptRequest().getServiceOfferId(), ServiceOfferConst.service_offer_1)) {
                        if (!KiteStringUtils.isEqual(oldAccountRelVO.getOfferInstId(), acctRel.getOfferInstId())) {
                            accountRel.setOldOfferInstId(oldAccountRelVO.getOfferInstId());
                        }
                        if (!KiteStringUtils.isEqual(oldAccountRelVO.getOfferName(), acctRel.getOfferName())) {
                            accountRel.setOldOfferName(oldAccountRelVO.getOfferName());
                        }
                        if (!KiteStringUtils.isEqual(oldAccountRelVO.getAcctId(), acctRel.getAcctId())) {
                            accountRel.setOldAcctId(oldAccountRelVO.getAcctId());
                        }
                        if (!KiteStringUtils.isEqual(oldAccountRelVO.getAcctName(), acctRel.getAcctName())) {
                            accountRel.setOldAcctName(oldAccountRelVO.getAcctName());
                        }
                        if (!KiteStringUtils.isEqual(oldAccountRelVO.getAcctItemId(), acctRel.getAcctItemId())) {
                            accountRel.setOldAcctItemId(oldAccountRelVO.getAcctItemId());
                        }
                    }
                    accountRelVos.add(accountRel);
                });
            }
            // 追加订购补充此逻辑
            if (KiteStringUtils.equalsAny(sceneInst.getServiceOfferId(),ServiceOfferConsts.SERVICE_OFFER_ORDER,ServiceOfferConsts.SERVICE_OFFER_FFGX)
                && KiteListUtils.isEmpty(accountRelVos)) {
                AccountRelVO accountRel = new AccountRelVO();
                accountRel.setOfferInstId(offerInst.getOfferInstId());
                accountRel.setOfferName(offerInst.getOfferName());
                accountRel.setAccNum(accNum);
                accountRelVos.add(accountRel);
            }
        }
        else {
            //信息录入只初始化
            /*String mainOfferInstId = querySceneInstService.getExtParameterValue(sceneInstId, "mainOfferInstId");
            List<KiteOfferInst> offerInsts = KiteStringUtils.isEmpty(mainOfferInstId) ?
                querySceneInstService.listMainOfferInsts(sceneInstId) :
                Arrays.asList(querySceneInstService
                    .getKiteInst(context.getAcceptRequest().getCustId(), InstType.MAIN_OFFER_INST, mainOfferInstId));*/

                // 临时处理逻辑 ：  add by sqy 2020/10/10 后续需要修复
                // 质检进来有时候会查询到附属商品的信息
            /*if (!KiteListUtils.isEmpty(offerInsts)) {
                for (KiteOfferInst offerInst : offerInsts) {

                }
            }*/
            String cateId = Optional.ofNullable(offerInst.getAttr("cateId")).map(KiteAttr::getDefaultValue).orElse("");
            if (!GoodsInfoTransfer.isAddRoleOffer(offerInst.getSpecId(), cateId)) {
                AccountRelVO accountRel = new AccountRelVO();
                accountRel.setOfferInstId(offerInst.getOfferInstId());
                accountRel.setOfferName(offerInst.getOfferName());
                accountRel.setAccNum(accNum);
                accountRelVos.add(accountRel);
            }
            if(ListUtil.isEmpty(accountRelVos)) {
                List<AccountRelVO> oldAccountRelVos = querySceneInstService //获取页面勾选的操作类型
                      .getExtParameterValue(sceneInstId, sceneInstId + "_ACCOUNTRELVOS");
                if(!ListUtil.isEmpty(oldAccountRelVos)) {
                	accountRelVos.add(oldAccountRelVos.get(0));
                }
            }else {
                operateSceneInstService.putExtParameter(sceneInstId, sceneInstId + "_ACCOUNTRELVOS", accountRelVos);
            }
        }
        AccountModuleVO accountModuleVO = new AccountModuleVO();
        accountModuleVO.setAccountRelInfo(accountRelVos);
        return accountModuleVO;
    }

    /**
     * 处理付费关系
     *
     * @param contextCust
     * @param offerInst
     * @param sceneInstId
     */
    private void dealAccount(CuccCustInfoDetailDTO contextCust, KiteOfferInst offerInst, String sceneInstId) {
        ILocalAccountService accountService = SpringUtil.getBean(ILocalAccountService.class);
        // 1、明细表的account_id存在情况下,查询账户信息。
        PageInfo<QryCustAccountReq> list = new PageInfo<QryCustAccountReq>();
        QryCustAccountReq qryCustAccountReq = null;
        // 如果账户ID为空，查客户下有CBSS账户标识的账户关联
        list = accountService
            .listCustAccountInfo(contextCust.getCustId(), "", "", "", "", "", "", contextCust.getProvinceCode(),
                ContextUtil.getLoginInfo().getUserInfo().getPostLanId(), null, 1, 5);
        dealAccountSpecAttr(list);
        qryCustAccountReq = list.getList().stream()
            .filter(qryCustAccount -> !KiteObjectUtils.isEmpty(qryCustAccount.getCustAccount()) && KiteStringUtils
                .isNotEmpty(qryCustAccount.getCustAccount().getCbssAccountCode()) && KiteStringUtils
                .isEqual("0", qryCustAccount.getCustAccount().getPayModeCode())).findFirst()
            .orElse(null); //筛选出有cbss账户标识的账户

        if (KiteObjectUtils.isEmpty(qryCustAccountReq) || KiteObjectUtils.isEmpty(qryCustAccountReq.getCustAccount())) {
            LOGGER.info("查询不到账户信息:group_id>>>>>>>>>>>>>>" + contextCust.getCustId());
        }
        else {
            commitAccount(contextCust.getCustId(), offerInst, qryCustAccountReq, sceneInstId); //提交付费关系
        }
    }

    private void dealAccountSpecAttr(PageInfo<QryCustAccountReq> list) {
        if (KiteListUtils.isNotEmpty(list.getList())) {
            list.getList().stream().forEach(account -> {
                if (Objects.nonNull(account.getCustAccount().getOpenDate())) {
                    Long time = account.getCustAccount().getOpenDate().getTime();
                    account.getCustAccount().setOpenDateFormat(DateUtils.formatTime(time));
                }
                String provinceName = LocalAttrHelper.getRegionName(account.getCustAccount().getProvinceCode());
                String eparchyName = LocalAttrHelper.getRegionName(account.getCustAccount().getEparchyCode());
                account.getCustAccount()
                    .setAccountLocation(KiteStringUtils.join(provinceName, Symbols.HYPHEN, eparchyName));
            });
        }
    }

    /**
     * 提交付费关系
     *
     * @param custId
     * @param offerInst
     */
    private void commitAccount(String custId, KiteOfferInst offerInst, QryCustAccountReq qryCustAccountReq,
        String sceneInstId) {
        IOperateSceneInstService operateSceneInstService = SpringUtil.getBean(IOperateSceneInstService.class);
        CustAccountDTO custAccountDTO = qryCustAccountReq.getCustAccount();
        CuccKiteOfferInstAcct offerInstAcct = new CuccKiteOfferInstAcct();
        KiteBeanUtils.copyProperties(custAccountDTO, offerInstAcct);
        dealOfferInstAcct(custAccountDTO, offerInstAcct, offerInst);
        if (KiteStringUtils.equals(offerInstAcct.getActionType().name(), ActionType.D.name())) {
            operateSceneInstService.deleteOfferInstAcct(sceneInstId, offerInstAcct.getOfferObjInstRelId());
        }
        else {
            String offerInstId = offerInstAcct.getOfferInstId();
            offerInstAcct.setInstType(InstType.OFFER_INST_ACCT);
            // 没有账户明细关系，明细ID传销售品id
            String offerId = "";
            if (!KiteObjectUtils.isEmpty(offerInst) && KiteStringUtils.isNotEmpty(offerInst.getOfferId())) {
                offerId = Optional.ofNullable(OfferCache.get(offerInst.getOfferId())).map(Offer::getOfferId).orElse("");
            }
            operateSceneInstService
                .addOfferInstAcct(sceneInstId, offerInstAcct, offerInstId, RelType.OFFER_OBJ_REL_TYPE_170000,
                    ActionType.A, KeyConsts.OFFER_ACCOUNT_ROLE, offerId);
        }
    }

    private void dealOfferInstAcct(CustAccountDTO custAccountDTO, CuccKiteOfferInstAcct offerInstAcct,
        KiteOfferInst offerInst) {
        offerInstAcct.setAcctId(Long.toString(custAccountDTO.getAcctId()));
        offerInstAcct.setAcctItemId("0"); //TODO
        offerInstAcct.setAcctName(custAccountDTO.getPayName());
        offerInstAcct.setActionType(ActionType.A);
        offerInstAcct.setCustId(Long.toString(custAccountDTO.getCustId()));
        offerInstAcct.setIsDefault("1");
        offerInstAcct.setOfferInstId(offerInst.getOfferInstId());
        offerInstAcct.setOfferName(offerInst.getOfferName());
        offerInstAcct.setPayLimit(custAccountDTO.getPayModeCode());
        offerInstAcct.setPayWay(custAccountDTO.getPayModeCode());
        String currentDate = DateFormatUtils.getFormatedDate();
        offerInstAcct.setStartDate(DateFormatUtils.getFirstDayInMonth(currentDate, "yyyy-MM"));
        offerInstAcct.setOpenDateFormat(offerInstAcct.getOpenDateFormat());
        offerInstAcct.setEndDate("2099-12");
    }

}
